package fr.lip6.move.care

import sdmakerz_v1.coresyntax.generator.interfaces.IContext
import sdmakerz_v1.coresyntax.sDMakerV1.Alt
import sdmakerz_v1.coresyntax.generator.interfaces.IConfigData
import sdmakerz_v1.coresyntax.generator.SDMakerV1IDProvider

class CareAltGen {
	private CareGen mainGenerator;
	
	new(CareGen mainGenerator){
		this.mainGenerator= mainGenerator;
	}
	
	def public
	CompileResult compile(IContext context, Alt alt){
	
	var IConfigData config= context.getConfigData
    var java.util.ArrayList<CompileResult> conseqNestedResults= 
    	new java.util.ArrayList<CompileResult>();
    var java.util.ArrayList<CompileResult> alterNestedResults= 
    	new java.util.ArrayList<CompileResult>();
    var java.util.ArrayList<String> namesToAdd= 
    	new java.util.ArrayList<String>();
    
    var CompileResult compRes

    var altID= "alt_id"+SDMakerV1IDProvider::computeID 
    var probTabID= "alt_probs_id"+SDMakerV1IDProvider::computeID
    var int i= 0; //pour distinguer les alternants possibles
    var java.util.ArrayList<Double> probas= 
    	new java.util.ArrayList<Double>();
    var boolean haveSetConseqProb= false;
    var boolean haveSetAlterProb= false;
    var boolean goodConfigProb=
             0<= config.globalProbInAlt &&
             config.globalProbInAlt <= 1
             
    //CALCUL DES PROBABILITES
    if(alt.conseq.probConseq != null &&
       0 < alt.conseq.probConseq.value &&  
           alt.conseq.probConseq.value <= 1){
            
        probas.add(alt.conseq.probConseq.value);
        haveSetConseqProb= true;
    }

    if(haveSetConseqProb==false){
        if(goodConfigProb){
            probas.add(config.globalProbInAlt);
        }
    }
    
    for(alter : alt.alters){
        haveSetAlterProb= false;
        
        if(alter.probAlter != null &&
            0 < alter.probAlter.value && 
                alter.probAlter.value <=1){
                probas.add(alter.probAlter.value);
                haveSetAlterProb= true;
        }
        
        if(haveSetAlterProb==false){
            if(goodConfigProb){
                probas.add(config.globalProbInAlt);
            }
        }
    }
    
    //FIN CALCUL DES PROBABILITES
	
	
    var CharSequence charSequenceResult=
    '''
«««TRAITEMENT DU CONSEQUENT»»
    «FOR elt: alt.conseq.conseq_elts»
    «SDMakerToCareUtils::toNullExp(compRes= mainGenerator.compile(context, elt))»
    «SDMakerToCareUtils::toNullExp(conseqNestedResults.add(compRes))»
    «ENDFOR»
    
    «IF conseqNestedResults.size == 1»
    /* CONSEQUENT: «altID» */
    «conseqNestedResults.get(0).charSequenceResult»
    «SDMakerToCareUtils::toNullExp(namesToAdd.add(conseqNestedResults.get(0).eltID))»
    «ELSEIF conseqNestedResults.size > 1»
    /* CONSEQUENT: «altID» */
    BlockList bloc_«altID»_conseq = new BlockList();
    
    «FOR conseqNestedResult: conseqNestedResults»
    «conseqNestedResult.charSequenceResult»
    «ENDFOR»
    
    // adds for bloc_«altID»_conseq
    «FOR conseqNestedResult: conseqNestedResults»
    bloc_«altID»_conseq.add(«conseqNestedResult.eltID»);
    «ENDFOR»
    «SDMakerToCareUtils::toNullExp(namesToAdd.add("bloc_"+altID+"_conseq"))»
    «ENDIF»

«««TRAITEMENT DES ALTERNANTS»»
   «SDMakerToCareUtils::toNullExp(i=0)»
   «FOR alter: alt.alters»
   «SDMakerToCareUtils::toNullExp(i=i+1)»
    «alterNestedResults.clear()»
    «FOR elt: alter.alter_elts»
    «SDMakerToCareUtils::toNullExp(compRes= mainGenerator.compile(context, elt))»
    «SDMakerToCareUtils::toNullExp(alterNestedResults.add(compRes))»
    «ENDFOR»
    
    «IF alterNestedResults.size == 1»
    /* ALTERNATIVE «i»: «altID» */
    «alterNestedResults.get(0).charSequenceResult»
    «SDMakerToCareUtils::toNullExp(namesToAdd.add(alterNestedResults.get(0).eltID))»
    //.add(«alterNestedResults.get(0).eltID»);
    «ELSEIF alterNestedResults.size > 1»
    /* ALTERNATIVE «i»: «altID» */
    BlockList bloc_«altID»_alter_num_«i» = new BlockList();
    
    «FOR alterNestedResult: alterNestedResults»
    «alterNestedResult.charSequenceResult»
    «ENDFOR»
    
    // adds for bloc_«altID»_alter_num_«i»
    «FOR alterNestedResult: alterNestedResults»
    bloc_«altID»_alter_num_«i».add(«alterNestedResult.eltID»);
    «ENDFOR»
    «SDMakerToCareUtils::toNullExp(namesToAdd.add("bloc_"+altID+"_alter_num_"+i))»
    «ENDIF»
    «ENDFOR»

«««FINALISATION DE L'ALTERNATIVE»»
   // FINALIZING «altID»
   Alt «altID»= new Alt();
   «FOR name : namesToAdd»
   «altID».add(«name»);
   «ENDFOR»
   
   «IF (probas.size()==(1+alt.alters.size()))»
«««   Si on a pu calculer une proba pour chaque cas
«««   alors on peut creer un alter avec proba
    «SDMakerToCareUtils::toNullExp(i=0)»
   double[] «probTabID»= new double[«probas.size()»];
   «FOR proba : probas»
   «probTabID»[«i»]= «proba»;
   «SDMakerToCareUtils::toNullExp(i=i+1)»
   «ENDFOR»
   «altID».setProbas(«probTabID»);
   «ENDIF»
    '''

    return new CompileResult(
    				charSequenceResult,
    				altID,
    				true)   
	}
}